package com.qyxx.designer.miniweb.web;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.qyxx.designer.miniweb.service.DesignManager;
import com.qyxx.designer.modules.mapper.JsonMapper;
import com.qyxx.designer.modules.utils.HttpClientUtils;
import com.qyxx.designer.modules.utils.ZipUtils;
import com.qyxx.designer.modules.web.FormatMessage;
import com.qyxx.designer.modules.web.Messages;
import com.qyxx.jwp.bean.Form;
import com.qyxx.jwp.bean.Module;
import com.qyxx.jwp.bean.Tab;
import com.qyxx.jwp.bean.Tabs;

/**
 * Urls: List page : GET /account/user/ Create page : GET /account/user/create
 * Create action : POST /account/user/save Update page : GET
 * /account/user/update/{id} Update action : POST /account/user/save/{id} Delete
 * action : POST /account/user/delete/{id} CheckLoginName ajax: GET
 * /account/user/checkLoginName?oldLoginName=a&loginName=b
 * 
 * 设计器控制类
 * 
 * @author gxj
 * @version 1.0 2012-6-28 下午03:26:12
 * @since jdk1.6
 */
@Controller
@SessionAttributes({ "loginUrl", "loginName", "configPath", "passwd" })
@RequestMapping(value = "/design")
public class DesignController {

	/**
	 * 登录地址
	 */
	public static final String LOGIN_PATH = "/ws/ws!view.action";

	/**
	 * 获取config文件包的url地址
	 */
	public static final String CONFIG_FILE_GET_PATH = "/ws/ws!getConfig.action?file=";

	/**
	 * 获取最新默认版本信息地址
	 */
	public static final String DEFAULT_VERSION_FILE_GET_PATH = "/ws/ws!getVersion.action";

	/**
	 * config文件下载路径
	 */
	public static final String CONFIG_PATH = "/config/";

	/**
	 * config文件名称
	 */
	public static final String CONFIG_FILE_NAME = "config.jwp";

	/**
	 * 版本文件名称
	 */
	public static final String VERSION_FILE_NAME = "version";

	/**
	 * file表单域名称
	 */
	public static final String CONFIG_FILE = "configFile";

	/**
	 * 更新config包
	 */
	public static final String UPGRADE_PATH = "/ws/ws!save.action";

	/**
	 * 强制更新config包
	 */
	public static final String FORCE_UPGRADE_PATH = "/ws/ws!forceUpgrade.action";

	/**
	 * 本地
	 */
	public static final String URL_TYPE_LOCAL = "local";

	/**
	 * 远程
	 */
	public static final String URL_TYPE_REMOTE = "remote";

	public static final String SYSTEM_PATH = "/system/";

	public static final String FLOW_PATH = SYSTEM_PATH + "workflow/";

	public static final String SIGNAVIO_SUFFIX = ".signavio.xml";
    
	public static final String BPMN20_SUFFIX = ".bpmn20.xml";
	
	public static final String JWP_SUFFIX=".jwp";
	
	public static final String JABDP_DEFAULT_PASS = "jabdp";

	public static final String JABDP_DEFAULT_USER = "admin";
	
	@Autowired
	private DesignManager designManager;

	private JsonMapper jm = new JsonMapper();

	/**
	 * 获取模块信息
	 * 
	 * @param key
	 * @return
	 */
	@RequestMapping(value = "module/getModule", produces = "text/plain;charset=UTF-8")
	@ResponseBody
	public String getModule(@RequestParam("key") String key,
			@RequestParam("treeId") String treeId,
			@ModelAttribute("configPath") Map<String, String> configPath) {
		// System.out.println(treeid);
		String[] keys = key.split("[.]");
		Module module = null;
		if (null != keys && keys.length >= 3) {
			String mPath = "/" + keys[0] + "/" + keys[1] + "/";
			String modulePath = configPath.get(treeId) + mPath;
			module = designManager.getModule(keys[2], modulePath);
		} else {
			module = new Module();
		}
		FormatMessage rtnMsg = new FormatMessage();
		rtnMsg.setMsg(module);
		String jsonStr = jm.toJson(rtnMsg);
		// System.out.println(module.toString());
		// System.out.println(jsonStr);
		return jsonStr;
	}

	/**
	 * 获取关联模块主表信息
	 * 
	 * @param key
	 * @return
	 */
	@RequestMapping(value = "module/getRelevanceModuleMaster", produces = "text/plain;charset=UTF-8")
	@ResponseBody
	public String getRelevanceModuleMaster(@RequestParam("key") String key,
			@RequestParam("treeId") String treeId,
			@ModelAttribute("configPath") Map<String, String> configPath) {
		String[] keys = key.split("[.]");
		Module module = null;
		Form form = null;
		ArrayList<Tab> tabs = new ArrayList<Tab>();
		if (null != keys && keys.length >= 3) {
			String mPath = "/" + keys[0] + "/" + keys[1] + "/";
			String modulePath = configPath.get(treeId) + mPath;
			module = designManager.getModule(keys[2], modulePath);
			for(Form f : module.getDataSource().getFormList()) {
				if(f.getIsMaster()) {
					form = f;
					break;
				}
			}
			for(Tabs ts : module.getDataSource().getTabsList()) {
				for(Tab t : ts.getTabList()) {
					if(t.getForm().equals(form.getKey())) {
						tabs.add(t);
					}
				}
			}
		}
		FormatMessage rtnMsg = new FormatMessage();
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("form", form);
		map.put("tabs", tabs);
		rtnMsg.setMsg(map);
		String jsonStr = jm.toJson(rtnMsg);
		return jsonStr;
	}

	/**
	 * 保存模块信息
	 * 
	 * @param moduleJson
	 * @return
	 */
	@RequestMapping(value = "module/saveModule", produces = "text/plain;charset=UTF-8")
	@ResponseBody
	public String saveModule(@RequestParam("moduleJson") String moduleJson,
			@RequestParam("treeId") String treeId,
			@RequestParam("key") String key,
			@RequestParam("newKey") String newKey,
			@ModelAttribute("configPath") Map<String, String> configPath) {
		// System.out.println("treeid:"+treeId);
		FormatMessage rtnMsg = new FormatMessage();
		if (newKey.equals("undefined") || newKey == "") {
			String[] keys = key.split("[.]");
			// System.out.println(keys.length);
			if (null != keys && keys.length >= 3) {
				Module module = jm.fromJson(moduleJson, Module.class);
				String mPath = "/" + keys[0] + "/" + keys[1] + "/";
				String modulePath = configPath.get(treeId) + mPath;
				designManager.saveModule(module, modulePath);
				//designManager.saveModuleJson(moduleJson, module, modulePath);
				rtnMsg.setMsg(true);
			} else {
				rtnMsg.setMsg(false);
			}
		} else {
			String[] newKeys = newKey.split("[.]");
			if (null != newKeys && newKeys.length >= 3) {
				Module module = jm.fromJson(moduleJson, Module.class);
				String mPath = "/" + newKeys[0] + "/" + newKeys[1] + "/";
				String modulePath = configPath.get(treeId) + mPath;
				designManager.saveModule(module, modulePath);
				rtnMsg.setMsg(true);
			} else {
				rtnMsg.setMsg(false);
			}
		}
		return jm.toJson(rtnMsg);
	}

	/**
	 * 登录远程服务器
	 * 
	 * @param loginUrl
	 * @param loginName
	 * @param passwd
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "login", produces = "text/plain;charset=UTF-8")
	@ResponseBody
	public String login(@RequestParam("urlType") String urlType,
			@RequestParam("loginUrl") String loginUrl,
			@RequestParam("loginName") String loginName,
			@RequestParam("passwd") String passwd, ModelMap model,
			HttpServletRequest request) {
		FormatMessage rtnMsg = new FormatMessage();
		if (URL_TYPE_LOCAL.equals(urlType)) {
			if (JABDP_DEFAULT_USER.equals(loginName) && JABDP_DEFAULT_PASS.equals(passwd)) {
				String cp = DesignController.getRealPath(request)
						+ URL_TYPE_LOCAL;
				Object config = model.get("configPath");
				if (config == null) {
					Map<String, String> m = DesignController.getLocalFile(cp);
					model.addAttribute("configPath", m);
				} else {
					Map<String, String> path = (Map<String, String>) config;
					Map<String, String> m = DesignController.getLocalFile(cp);
					Set<Map.Entry<String, String>> set = m.entrySet();
					for (Iterator<Map.Entry<String, String>> it = set
							.iterator(); it.hasNext();) {
						Map.Entry<String, String> entry = (Map.Entry<String, String>) it
								.next();
						path.put(entry.getKey(), entry.getValue());
					}
					model.addAttribute("configPath", path);
				}
				//

				model.addAttribute("loginUrl", loginUrl);
				model.addAttribute("loginName", loginName);
				model.addAttribute("passwd", passwd);
			} else {
				rtnMsg.setFlag(Messages.FAIL);
				rtnMsg.setMsg("用户名或密码错误");
			}
		} else {
			String url = loginUrl + LOGIN_PATH;
			url += "?loginName=" + loginName + "&passwd=" + passwd;
			try {
				String result = HttpClientUtils.get(url);
				FormatMessage fm = jm.fromJson(result, FormatMessage.class);
				if (Messages.SUCCESS.equals(fm.getFlag())) {
					String dnUrl = loginUrl + CONFIG_FILE_GET_PATH
							+ fm.getMsg();
					String basePath = DesignController.getRealPath(request)
							+ URL_TYPE_REMOTE;
					String destFilePath = getConfigPath(basePath);
					FileUtils.forceMkdir(new File(destFilePath));
					// config文件下载
					String dfp = HttpClientUtils.downloadFile(dnUrl,
							destFilePath + CONFIG_FILE_NAME, null);
					if (StringUtils.isNotBlank(dfp)) {
						ZipUtils.unzip(dfp, destFilePath);
					}

					Object config = model.get("configPath");
					if (config == null) {
						Map<String, String> m = new HashMap<String, String>();
						String key = destFilePath.replace(basePath, "")
								.replace("/", "");
						m.put(key, destFilePath + CONFIG_PATH);
						model.addAttribute("configPath", m);
					} else {
						Map<String, String> path = (Map<String, String>) config;
						Set<Map.Entry<String, String>> set = path.entrySet();
						for (Iterator<Map.Entry<String, String>> it = set
								.iterator(); it.hasNext();) {
							Map.Entry<String, String> entry = (Map.Entry<String, String>) it
									.next();
							if (entry.getValue().indexOf("remote") != -1) {
								path.remove(entry.getKey());
							}
						}
						String key = destFilePath.replace(basePath, "")
								.replace("/", "");
						path.put(key, destFilePath + CONFIG_PATH);
						model.addAttribute("configPath", path);

					}

					Map<String, String> m = new HashMap<String, String>();
					// m.put(key, destFilePath+ CONFIG_PATH);
					// model.addAttribute("configPath", destFilePath +
					// CONFIG_PATH);
					// model.addAttribute("configPath", m);
					model.addAttribute("loginUrl", loginUrl);
					model.addAttribute("loginName", loginName);
					model.addAttribute("passwd", passwd);
				} else {
					rtnMsg.setFlag(Messages.FAIL);
					rtnMsg.setMsg(fm.getMsg());
				}
			} catch (Exception e) {
				e.printStackTrace();
				rtnMsg.setFlag(Messages.ERROR);
				rtnMsg.setMsg("服务器地址" + loginUrl + "输入不正确或服务未开启，异常描述："
						+ e.getMessage());
			}
		}
		return jm.toJson(rtnMsg);
	}

	/**
	 * 升级config包
	 * 
	 * @param loginName
	 * @return
	 */
	@RequestMapping(value = "upgrade", produces = "text/plain;charset=UTF-8")
	@ResponseBody
	public String upgrade(@RequestParam("loginUrl") String loginUrl,
			@ModelAttribute("configPath") Map<String, String> configPath,
			@RequestParam("loginName") String loginName,
			@RequestParam("passwd") String passwd,
			@RequestParam("isFullUpdate") Boolean isFullUpdate, 
			@RequestParam("treeId") String treeId) {
		FormatMessage rtnMsg = new FormatMessage();
		String url = loginUrl + UPGRADE_PATH;
		url += "?loginName=" + loginName + "&passwd=" + passwd + "&isFullUpdate=" + isFullUpdate;
		String path = configPath.get(treeId);
		try {
			// 先删除已有压缩文件，再压缩修改后的文件，最后上传更新服务器
			String sourceFilePath = path + "../" + CONFIG_FILE_NAME;
			FileUtils.deleteQuietly(new File(sourceFilePath));
			ZipUtils.zip(path, sourceFilePath);
			String result = HttpClientUtils.uploadFile(url, sourceFilePath,
					CONFIG_FILE, "UTF-8");
			System.out.println(result);
			rtnMsg = jm.fromJson(result, FormatMessage.class);
			if (null != rtnMsg) {
				if (Messages.SUCCESS.equals(rtnMsg.getFlag())) {
					Object obj = rtnMsg.getMsg();
					if (obj instanceof Boolean) {
						// 部署成功，更新版本文件
						String srcUrl = loginUrl
								+ DEFAULT_VERSION_FILE_GET_PATH;
						String destUrl = path + VERSION_FILE_NAME;
						HttpClientUtils.downloadFile(srcUrl, destUrl, "UTF-8");
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			rtnMsg.setFlag(Messages.FAIL);
			rtnMsg.setMsg(e.getMessage());
		}
		return jm.toJson(rtnMsg);
	}

	/**
	 * 强制升级config包
	 * 
	 * @param loginName
	 * @return
	 */
	@RequestMapping(value = "forceUpgrade", produces = "text/plain;charset=UTF-8")
	@ResponseBody
	public String forceUpgrade(@RequestParam("loginUrl") String loginUrl,
			@ModelAttribute("configPath") Map<String, String> configPath,
			@RequestParam("loginName") String loginName,
			@RequestParam("passwd") String passwd,
			@RequestParam("isFullUpdate") Boolean isFullUpdate, 
			@RequestParam("treeId") String treeId,
			@RequestParam("jwpName") String jwpName) {
		FormatMessage rtnMsg = new FormatMessage();
		String url = loginUrl + FORCE_UPGRADE_PATH;
		url += "?loginName=" + loginName + "&passwd=" + passwd  + "&isFullUpdate=" + isFullUpdate + "&file="
				+ jwpName;
		String path = configPath.get(treeId);
		try {
			String result = HttpClientUtils.get(url);
			rtnMsg = jm.fromJson(result, FormatMessage.class);
			if (null != rtnMsg) {
				if (Messages.SUCCESS.equals(rtnMsg.getFlag())) {
					// 部署成功，更新版本文件
					String srcUrl = loginUrl + DEFAULT_VERSION_FILE_GET_PATH;
					String destUrl = path + VERSION_FILE_NAME;
					HttpClientUtils.downloadFile(srcUrl, destUrl, null);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			rtnMsg.setFlag(Messages.FAIL);
			rtnMsg.setMsg(e.getMessage());
		}
		return jm.toJson(rtnMsg);
	}

	/**
	 * 获取应用路径
	 * 
	 * @param request
	 * @return
	 */
	public static String getRealPath(HttpServletRequest request) {
		String basePath = request.getSession().getServletContext()
				.getRealPath("/");
		return basePath + "/";
	}

	/**
	 * 获取Session
	 */
	@RequestMapping(value = "getSession", produces = "text/plain;charset=UTF-8")
	@ResponseBody
	public String getSession(HttpServletRequest request) {
		HttpSession session = request.getSession();
		FormatMessage rtnMsg = new FormatMessage();
		if (session.getAttribute("loginName") != null) {
			rtnMsg.setMsg(true);
		} else {
			rtnMsg.setMsg(false);
		}
		String jsonStr = jm.toJson(rtnMsg);
		return jsonStr;
	}

	/**
	 * 获取config包文件夹地址
	 * 
	 * @param basePath
	 * @return
	 */
	public String getConfigPath(String basePath) {
		StringBuffer sb = new StringBuffer();
		sb.append(basePath);
		sb.append("/");
		sb.append(DateFormatUtils.format(System.currentTimeMillis(),
				"yyyyMMddHHmmssSSS"));
		sb.append("/");
		return sb.toString();
	}

	public static void main(String[] args) {
		String s = "module.bill.contracts";
		String[] ss = s.split("[.]");
		System.out.println(ss.length);
	}

	/**
	 * 获取本地文件夹下面所有文件
	 * 
	 * @param path
	 * @return
	 */
	public static Map<String, String> getLocalFile(String path) {
		Map pathMap = new HashMap<String, String>();
		File f = new File(path);
		File[] list = f.listFiles();
		if (list != null) {
			for (File l : list) {
				String key = l.getName();
				// System.out.println(l.getPath());
				// String key= l.getPath().substring(path.length()+1,
				// l.getPath().length());
				String reg = "[0-9]{" + key.length() + "}";
				if (key.matches(reg)) {
					// String value = l.getPath()+"\config";
					pathMap.put(key, l.getPath() + "/config/");
				}
			}
		}
		return pathMap;
	}

	/**
	 * 获取流程文件路径
	 * 
	 * @param treeId
	 * @param configPath
	 * @return
	 */
	@RequestMapping(value = "module/getFlowPath", produces = "text/plain;charset=UTF-8")
	@ResponseBody
	public String getFlowPath(@RequestParam("treeId") String treeId,
			@ModelAttribute("configPath") Map<String, String> configPath) {
		String flowPath = configPath.get(treeId);
		flowPath += FLOW_PATH;
		File file = new File(flowPath);
		if (!file.exists()) {
			file.mkdir();
		}
		FormatMessage rtnMsg = new FormatMessage();
		rtnMsg.setMsg(flowPath);
		String jsonStr = jm.toJson(rtnMsg);
		return jsonStr;
	}

	/**
	 * 删除指定流程文件
	 * 
	 * @param treeId
	 * @param flowName
	 * @param configPath
	 * @return
	 */
	@RequestMapping(value = "module/delFlow", produces = "text/plain;charset=UTF-8")
	@ResponseBody
	public String delFlow(@RequestParam("treeId") String treeId,
			@RequestParam("flowName") String flowName,
			@ModelAttribute("configPath") Map<String, String> configPath) {
		String flowPath = configPath.get(treeId);
		flowPath += FLOW_PATH + flowName;
		String bpmnPath = flowPath + BPMN20_SUFFIX;
		String signavioPath = flowPath + SIGNAVIO_SUFFIX;
		try {
			FileUtils.forceDelete(new File(bpmnPath));
			FileUtils.forceDelete(new File(signavioPath));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		FormatMessage rtnMsg = new FormatMessage();
		rtnMsg.setMsg(flowName);
		String jsonStr = jm.toJson(rtnMsg);
		return jsonStr;
	}

	/**
	 * 跳转首页
	 * 
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "index")
	public String index(Model model) {
		return "design/index";
	}

}
